/*
 * FaceCat图形通讯框架
 * 著作权编号:2015SR229355+2020SR0266727
 * 上海卷卷猫信息技术有限公司
 */

using System;
using System.Collections.Generic;

namespace FaceCat
{
    /// <summary>
    /// 树节点
    /// </summary>
    public class FCTreeNode : FCGridViewCell
    {
        /// <summary>
        /// 创建节点
        /// </summary>
        public FCTreeNode()
        {
        }

        /// <summary>
        /// 析构函数
        /// </summary>
        ~FCTreeNode()
        {
            m_nodes.clear();
        }

        /// <summary>
        /// 子节点
        /// </summary>
        public ArrayList<FCTreeNode> m_nodes = new ArrayList<FCTreeNode>();

        /// <summary>
        /// 文字
        /// </summary>
        public String m_text = "";

        public bool m_allowDragIn = false;

        /// <summary>
        /// 获取是否可以拖入节点
        /// </summary>
        public virtual bool allowDragIn()
        {
            return m_allowDragIn;
        }

        /// <summary>
        /// 设置是否可以拖入节点
        /// </summary>
        public virtual void setAllowDragIn(bool value)
        {
            m_allowDragIn = value;
        }

        public bool m_allowDragOut = false;

        /// <summary>
        /// 获取是否可以拖出节点
        /// </summary>
        public virtual bool allowDragOut()
        {
            return m_allowDragOut;
        }

        /// <summary>
        /// 设置是否可以拖出节点
        /// </summary>
        public virtual void setAllowDragOut(bool value)
        {
            m_allowDragOut = value;
        }

        public bool m_checked = false;

        /// <summary>
        /// 获取复选框是否选中
        /// </summary>
        public virtual bool isChecked()
        {
            return m_checked;
        }

        /// <summary>
        /// 设置复选框是否选中
        /// </summary>
        public virtual void setChecked(bool value)
        {
            if (m_checked != value)
            {
                m_checked = value;
                checkChildNodes(m_nodes, m_checked);
            }
        }

        public bool m_expended = true;

        /// <summary>
        /// 获取是否展开节点
        /// </summary>
        public virtual bool isExpended()
        {
            return m_expended;
        }

        /// <summary>
        /// 设置是否展开节点
        /// </summary>
        public virtual void setExpended(bool value)
        {
            m_expended = value;
        }

        public FCTreeNode m_parent;

        /// <summary>
        /// 获取父节点
        /// </summary>
        public virtual FCTreeNode getParent()
        {
            return m_parent;
        }

        /// <summary>
        /// 设置父节点
        /// </summary>
        public virtual void setParent(FCTreeNode value)
        {
            m_parent = value;
        }

        public FCGridColumn m_targetColumn;

        /// <summary>
        /// 获取目标列
        /// </summary>
        public virtual FCGridColumn getTargetColumn()
        {
            return m_targetColumn;
        }

        /// <summary>
        /// 设置目标列
        /// </summary>
        public void setTargetColumn(FCGridColumn value)
        {
            m_targetColumn = value;
        }

        public int m_indent;

        /// <summary>
        /// 获取文字缩进距离
        /// </summary>
        public virtual int getIndent()
        {
            return m_indent;
        }

        public FCTree m_tree;

        /// <summary>
        /// 获取树视图
        /// </summary>
        public virtual FCTree getTree()
        {
            return m_tree;
        }

        /// <summary>
        /// 设置树视图
        /// </summary>
        public virtual void setTree(FCTree value)
        {
            m_tree = value;
        }

        public String m_value;

        /// <summary>
        /// 获取值
        /// </summary>
        public virtual String getValue()
        {
            return m_value;
        }

        /// <summary>
        /// 设置值
        /// </summary>
        public virtual void setValue(String value)
        {
            m_value = value;
        }

        /// <summary>
        /// 添加节点
        /// </summary>
        /// <param name="node">节点</param>
        public virtual void appendNode(FCTreeNode node)
        {
            node.setParent(this);
            node.setTree(m_tree);
            node.onAddingNode(-1);
            m_nodes.add(node);
        }

        /// <summary>
        /// 选中所有子节点
        /// </summary>
        /// <param name="nodes">节点集合</param>
        /// <param name="isChecked">是否选中</param>
        public virtual void checkChildNodes(ArrayList<FCTreeNode> nodes, bool isChecked)
        {
            int nodeSize = m_nodes.size();
            for (int i = 0; i < nodeSize; i++)
            {
                FCTreeNode node = nodes.get(i);
                node.setChecked(isChecked);
                ArrayList<FCTreeNode> childNodes = node.getChildNodes();
                if (childNodes != null && childNodes.size() > 0)
                {
                    checkChildNodes(childNodes, isChecked);
                }
            }
        }

        /// <summary>
        /// 清除所有节点
        /// </summary>
        public virtual void clearNodes()
        {
            while (m_nodes.size() > 0)
            {
                removeNode(m_nodes.get(m_nodes.size() - 1));
            }
        }

        /// <summary>
        /// 折叠节点
        /// </summary>
        public virtual void collapse()
        {
            if (m_nodes.size() > 0)
            {
                m_expended = false;
                collapseChildNodes(m_nodes, false);
            }
        }

        /// <summary>
        /// 折叠所有节点
        /// </summary>
        public virtual void collapseAll()
        {
            if (m_nodes.size() > 0)
            {
                m_expended = false;
                collapseChildNodes(m_nodes, true);
            }
        }

        /// <summary>
        /// 折叠子节点
        /// </summary>
        /// <param name="nodes">节点集合</param>
        /// <param name="expendAll">是否折叠儿子节点</param>
        public virtual void collapseChildNodes(ArrayList<FCTreeNode> nodes, bool collapseAll)
        {
            int nodeSize = nodes.size();
            for (int i = 0; i < nodeSize; i++)
            {
                FCTreeNode node = nodes.get(i);
                if (collapseAll)
                {
                    node.setExpended(false);
                }
                node.getRow().setVisible(false);
                ArrayList<FCTreeNode> childNodes = node.getChildNodes();
                if (childNodes != null && childNodes.size() > 0)
                {
                    collapseChildNodes(childNodes, collapseAll);
                }
            }
        }

        /// <summary>
        /// 展开节点
        /// </summary>
        public virtual void expend()
        {
            if (m_nodes.size() > 0)
            {
                m_expended = true;
                expendChildNodes(m_nodes, true, false);
            }
        }

        /// <summary>
        /// 展开所有节点
        /// </summary>
        public virtual void expendAll()
        {
            if (m_nodes.size() > 0)
            {
                m_expended = true;
                expendChildNodes(m_nodes, true, true);
            }
        }

        /// <summary>
        /// 展开所有的节点
        /// </summary>
        /// <param name="nodes">节点集合</param>
        /// <param name="parentExpened">父节点是否展开</param>
        /// <param name="expendAll">儿子节点是否展开</param>
        public virtual void expendChildNodes(ArrayList<FCTreeNode> nodes, bool parentExpened, bool expendAll)
        {
            int nodeSize = nodes.size();
            for (int i = 0; i < nodeSize; i++)
            {
                FCTreeNode node = nodes.get(i);
                bool pExpended = parentExpened;
                if (expendAll)
                {
                    pExpended = true;
                    node.getRow().setVisible(true);
                    node.setExpended(true);
                }
                else
                {
                    if (parentExpened)
                    {
                        node.getRow().setVisible(true);
                    }
                    else
                    {
                        node.getRow().setVisible(false);
                    }
                    if (!node.isExpended())
                    {
                        pExpended = false;
                    }
                }
                ArrayList<FCTreeNode> childNodes = node.getChildNodes();
                if (childNodes != null && childNodes.size() > 0)
                {
                    expendChildNodes(childNodes, pExpended, expendAll);
                }
            }
        }

        /// <summary>
        /// 获取子节点
        /// </summary>
        /// <returns>子节点</returns>
        public virtual ArrayList<FCTreeNode> getChildNodes()
        {
            return m_nodes;
        }

        /// <summary>
        /// 获取最后节点的索引
        /// </summary>
        /// <param name="nodes">节点</param>
        /// <returns>索引</returns>
        public virtual FCTreeNode getLastNode(ArrayList<FCTreeNode> nodes)
        {
            int size = nodes.size();
            if (size > 0)
            {
                for (int i = size - 1; i >= 0; i--)
                {
                    FCTreeNode lastNode = nodes.get(i);
                    if (lastNode.getRow() != null)
                    {
                        ArrayList<FCTreeNode> childNodes = lastNode.getChildNodes();
                        FCTreeNode subLastNode = getLastNode(childNodes);
                        if (subLastNode != null)
                        {
                            return subLastNode;
                        }
                        else
                        {
                            return lastNode;
                        }
                    }
                }
            }
            return null;
        }

        /// <summary>
        /// 获取节点的索引
        /// </summary>
        /// <param name="node">节点</param>
        /// <returns>索引</returns>
        public virtual int getNodeIndex(FCTreeNode node)
        {
            int nodeSize = m_nodes.size();
            for (int i = 0; i < nodeSize; i++)
            {
                if (m_nodes.get(i) == node)
                {
                    return i;
                }
            }
            return -1;
        }

        /// <summary>
        /// 获取要绘制的文本
        /// </summary>
        /// <returns>要绘制的文本</returns>
        public override String getPaintText()
        {
            return getText();
        }

        /// <summary>
        /// 获取属性值
        /// </summary>
        /// <param name="name">属性名称</param>
        /// <param name="value">返回属性值</param>
        /// <param name="type">返回属性类型</param>
        public override void getAttribute(String name, ref String value, ref String type)
        {
            switch (name)
            {
                case "allowdragin":
                    type = "bool";
                    value = FCTran.boolToStr(allowDragIn());
                    break;
                case "allowdragout":
                    type = "bool";
                    value = FCTran.boolToStr(allowDragOut());
                    break;
                case "checked":
                    type = "bool";
                    value = FCTran.boolToStr(isChecked());
                    break;
                case "expended":
                    type = "bool";
                    value = FCTran.boolToStr(isExpended());
                    break;
                case "value":
                    type = "text";
                    value = getValue();
                    break;
                default:
                    base.getAttribute(name, ref value, ref type);
                    break;
            }
        }

        /// <summary>
        /// 获取属性名称列表
        /// </summary>
        /// <returns>属性名称列表</returns>
        public override ArrayList<String> getAttributeNames()
        {
            ArrayList<String> attributeNames = base.getAttributeNames();
            attributeNames.AddRange(new String[] { "AllowDragIn", "AllowDragOut", "Checked", "Expended", "Value" });
            return attributeNames;
        }

        /// <summary>
        /// 获取字符型数值
        /// </summary>
        /// <returns>字符型数值</returns>
        public override String getString()
        {
            return m_text;
        }

        /// <summary>
        /// 插入节点
        /// </summary>
        /// <param name="index">索引</param>
        /// <param name="node">节点</param>
        public virtual void insertNode(int index, FCTreeNode node)
        {
            int rowIndex = -1;
            if (index == 0)
            {
                if (node.getParent() != null)
                {
                    rowIndex = node.getParent().getRow().getIndex() + 1;
                }
                else
                {
                    rowIndex = 0;
                }
            }
            else
            {
                if (m_nodes.size() > 0)
                {
                    rowIndex = m_nodes.get(index).getRow().getIndex();
                }
            }
            node.setTree(m_tree);
            node.setParent(this);
            node.onAddingNode(rowIndex);
            m_nodes.Insert(index, node);
        }

        /// <summary>
        /// 父节点是否可见
        /// </summary>
        /// <param name="node">节点</param>
        /// <returns>是否可见</returns>
        public virtual bool isNodeVisible(FCTreeNode node)
        {
            FCTreeNode parentNode = node.getParent();
            if (parentNode != null)
            {
                if (!parentNode.isExpended())
                {
                    return false;
                }
                else
                {
                    return isNodeVisible(parentNode);
                }
            }
            else
            {
                return true;
            }
        }

        /// <summary>
        /// 添加节点
        /// </summary>
        /// <param name="index">行索引</param>
        public virtual void onAddingNode(int index)
        {
            FCGridRow row = getRow();
            if (row == null)
            {
                //创建行
                row = new FCGridRow();
                FCTreeNode parentNode = m_parent;
                if (parentNode == null)
                {
                    if (index != -1)
                    {
                        //插入行
                        m_tree.insertRow(index, row);
                        //重置行的索引
                        ArrayList<FCGridRow> rows = m_tree.getRows();
                        int rowSize = rows.size();
                        for (int i = 0; i < rowSize; i++)
                        {
                            rows.get(i).setIndex(i);
                        }
                    }
                    else
                    {
                        //添加行
                        m_tree.addRow(row);
                        //设置索引
                        ArrayList<FCGridRow> rows = m_tree.getRows();
                        row.setIndex(rows.size() - 1);
                    }
                    row.addCell(0, this);
                    m_targetColumn = m_tree.getColumn(0);
                }
                else
                {
                    //获取行索引
                    int rowIndex = parentNode.getRow().getIndex() + 1;
                    if (index != -1)
                    {
                        rowIndex = index;
                    }
                    else
                    {
                        //查找上个节点      
                        FCTreeNode lastNode = getLastNode(parentNode.getChildNodes());
                        if (lastNode != null)
                        {
                            if (lastNode.getRow() == null)
                            {
                                return;
                            }
                            rowIndex = lastNode.getRow().getIndex() + 1;
                        }
                    }
                    //插入行
                    m_tree.insertRow(rowIndex, row);
                    ArrayList<FCGridRow> rows = m_tree.getRows();
                    int rowSize = rows.size();
                    //重置索引
                    if (rowIndex == rowSize - 1)
                    {
                        row.setIndex(rowIndex);
                    }
                    else
                    {
                        for (int i = 0; i < rowSize; i++)
                        {
                            rows.get(i).setIndex(i);
                        }
                    }
                    row.addCell(0, this);
                    m_targetColumn = m_tree.getColumn(parentNode.m_targetColumn.getIndex() + 1);
                }
                setColSpan(m_tree.getColumns().size());
                //添加子节点
                if (m_nodes != null && m_nodes.size() > 0)
                {
                    int nodeSize = m_nodes.size();
                    for (int i = 0; i < nodeSize; i++)
                    {
                        m_nodes.get(i).setTree(m_tree);
                        m_nodes.get(i).onAddingNode(-1);
                    }
                }
                row.setVisible(isNodeVisible(this));
            }
        }

        /// <summary>
        /// 绘制复选框
        /// </summary>
        /// <param name="paint">绘图对象</param>
        /// <param name="rect">区域</param>
        public virtual void onPaintCheckBox(FCPaint paint, FCRect rect)
        {
            if (m_checked)
            {
                if (m_tree.getCheckedImage() != null && m_tree.getCheckedImage().Length > 0)
                {
                    paint.drawImage(m_tree.getCheckedImage(), rect);
                }
                else
                {
                    FCRect innerRect = new FCRect(rect.left + 2, rect.top + 2, rect.right - 3, rect.bottom - 3);
                    if (rect.right - rect.left < 4 || rect.bottom - rect.top < 4)
                    {
                        innerRect = rect;
                    }
                    FCPoint[] pp = new FCPoint[3];
                    pp[0] = new FCPoint(innerRect.left, innerRect.top + 8);
                    pp[1] = new FCPoint(innerRect.left + 6, innerRect.bottom);
                    pp[2] = new FCPoint(innerRect.right - 1, innerRect.top);
                    paint.drawRoundRect(FCColor.Border, 1, 0, rect, 4);
                    paint.drawPolyline(FCColor.Text, 2, 0, pp);
                }
            }
            else
            {
                if (m_tree.getUnCheckedImage() != null && m_tree.getUnCheckedImage().Length > 0)
                {
                    paint.drawImage(m_tree.getUnCheckedImage(), rect);
                }
                else
                {
                    paint.drawRect(FCColor.Border, 1, 0, rect);
                }
            }
        }

        /// <summary>
        /// 绘制节点
        /// </summary>
        /// <param name="paint">绘图对象</param>
        /// <param name="rect">区域</param>
        public virtual void onPaintNode(FCPaint paint, FCRect rect)
        {
            if (m_expended)
            {
                if (m_tree.getExpendedNodeImage() != null && m_tree.getExpendedNodeImage().Length > 0)
                {
                    paint.drawImage(m_tree.getExpendedNodeImage(), rect);
                    return;
                }
            }
            else
            {
                if (m_tree.getCollapsedNodeImage() != null && m_tree.getCollapsedNodeImage().Length > 0)
                {
                    paint.drawImage(m_tree.getCollapsedNodeImage(), rect);
                    return;
                }
            }
            int width = rect.right - rect.left;
            int height = rect.bottom - rect.top;
            FCPoint[] points = new FCPoint[3];
            //展开
            if (m_expended)
            {
                points[0] = new FCPoint(rect.left, rect.top);
                points[1] = new FCPoint(rect.left + width, rect.top);
                points[2] = new FCPoint(rect.left + width / 2, rect.top + height);
            }
            //折叠
            else
            {
                points[0] = new FCPoint(rect.left, rect.top);
                points[1] = new FCPoint(rect.left, rect.top + height);
                points[2] = new FCPoint(rect.left + width, rect.top + height / 2);
            }
            FCGrid grid = getGrid();
            paint.fillPolygon(grid.getTextColor(), points);
        }

        /// <summary>
        /// 重绘方法
        /// </summary>
        /// <param name="paint">绘图对象</param>
        /// <param name="rect">矩形</param>
        /// <param name="clipRect">裁剪矩形</param>
        /// <param name="isAlternate">是否交替行</param>
        public override void onPaint(FCPaint paint, FCRect rect, FCRect clipRect, bool isAlternate)
        {
            int clipW = clipRect.right - clipRect.left;
            int clipH = clipRect.bottom - clipRect.top;
            FCGrid grid = getGrid();
            FCGridRow row = getRow();
            if (clipW > 0 && clipH > 0 && grid != null && getColumn() != null && row != null && getTargetColumn() != null)
            {
                int width = rect.right - rect.left;
                int height = rect.bottom - rect.top;
                int scrollH = 0;
                FCHScrollBar hscrollBar = grid.getHScrollBar();
                if (hscrollBar != null && hscrollBar.isVisible())
                {
                    scrollH = hscrollBar.getPos();
                }
                FCFont font = null;
                long backColor = FCColor.None;
                long textColor = FCColor.None;

                FCGridRowStyle rowStyle = grid.getRowStyle();
                if (isAlternate)
                {
                    FCGridRowStyle alternateRowStyle = grid.getAlternateRowStyle();
                    if (alternateRowStyle != null)
                    {
                        rowStyle = alternateRowStyle;
                    }
                }
                if (rowStyle != null)
                {
                    bool selected = false;
                    ArrayList<FCGridRow> selectedRows = grid.getSelectedRows();
                    int selectedRowsSize = selectedRows.size();
                    for (int i = 0; i < selectedRowsSize; i++)
                    {
                        if (selectedRows[i] == row)
                        {
                            selected = true;
                            break;
                        }
                    }
                    //if (backColor == FCColor.None) {
                    //    //选中
                    //    if (selected) {
                    //        backColor = rowStyle.getSelectedBackColor();
                    //    }
                    //        //悬停
                    //    else if (getRow() == getGrid().getHoveredRow()) {
                    //        backColor = rowStyle.getHoveredBackColor();
                    //    }
                    //        //普通
                    //    else {
                    //        backColor = rowStyle.getBackColor();
                    //    }
                    //}
                    if (font == null)
                    {
                        font = rowStyle.getFont();
                    }
                    if (textColor == FCColor.None)
                    {
                        //选中
                        if (selected)
                        {
                            textColor = rowStyle.getSelectedTextColor();
                        }
                        //悬停
                        else if (getRow() == getGrid().getHoveredRow())
                        {
                            textColor = rowStyle.getHoveredTextColor();
                        }
                        //普通
                        else
                        {
                            textColor = rowStyle.getTextColor();
                        }
                    }
                }

                bool autoEllipsis = m_tree.autoEllipsis();
                FCGridCellStyle style = getStyle();
                if (style != null)
                {
                    if (style.autoEllipsis())
                    {
                        autoEllipsis = style.autoEllipsis();
                    }
                    if (m_style.getBackColor() != FCColor.None)
                    {
                        backColor = style.getBackColor();
                    }
                    if (style.getFont() != null)
                    {
                        font = style.getFont();
                    }
                    if (m_style.getTextColor() != FCColor.None)
                    {
                        textColor = style.getTextColor();
                    }
                }

                //绘制背景
                paint.fillRect(backColor, rect);
                FCRect headerRect = getTargetColumn().getBounds();
                headerRect.left += getGrid().getHorizontalOffset() - scrollH;
                headerRect.top += getGrid().getVerticalOffset() - scrollH;
                int left = headerRect.left;
                //绘制复选框
                if (m_tree.hasCheckBoxes())
                {
                    int cw = m_tree.getCheckBoxSize().cx;
                    int ch = m_tree.getCheckBoxSize().cy;
                    FCRect checkBoxRect = new FCRect();
                    checkBoxRect.left = left;
                    checkBoxRect.top = rect.top + (height - ch) / 2;
                    checkBoxRect.right = checkBoxRect.left + cw;
                    checkBoxRect.bottom = checkBoxRect.top + ch;
                    onPaintCheckBox(paint, checkBoxRect);
                    left += cw + 10;
                }
                //绘制折叠展开的标志
                int nw = m_tree.getNodeSize().cx;
                int nh = m_tree.getNodeSize().cy;
                if (m_nodes.size() > 0)
                {
                    FCRect nodeRect = new FCRect();
                    nodeRect.left = left + 4;
                    nodeRect.top = rect.top + (height - nh) / 2;
                    nodeRect.right = nodeRect.left + nw;
                    nodeRect.bottom = nodeRect.top + nh;
                    onPaintNode(paint, nodeRect);
                }
                left += nw + 10;
                m_indent = left;
                String text = getPaintText();
                //绘制文字
                if (text != null)
                {
                    FCSize tSize = paint.textSize(text, font, -1);
                    FCRect tRect = new FCRect();
                    tRect.left = left;
                    tRect.top = rect.top + (row.getHeight() - tSize.cy) / 2;
                    tRect.right = tRect.left + tSize.cx;
                    tRect.bottom = tRect.top + tSize.cy;
                    if (autoEllipsis && (tRect.right > clipRect.right || tRect.bottom > clipRect.bottom))
                    {
                        if (tRect.right > clipRect.right)
                        {
                            tRect.right = clipRect.right;
                        }
                        if (tRect.bottom > clipRect.bottom)
                        {
                            tRect.bottom = clipRect.bottom;
                        }
                        paint.drawTextAutoEllipsis(text, textColor, font, tRect);
                    }
                    else
                    {
                        paint.drawText(text, textColor, font, tRect, -1);
                    }
                }
            }
            onPaintView(paint, rect, clipRect);
        }

        /// <summary>
        /// 移除节点方法
        /// </summary>
        public virtual void onRemovingNode()
        {
            m_indent = 0;
            FCGridRow row = getRow();
            if (row != null)
            {
                if (m_nodes != null && m_nodes.size() > 0)
                {
                    int nodeSize = m_nodes.size();
                    for (int i = 0; i < nodeSize; i++)
                    {
                        m_nodes.get(i).onRemovingNode();
                    }
                }
                m_tree.removeRow(row);
                row.clearCells();
                ArrayList<FCGridRow> rows = m_tree.getRows();
                int rowSize = rows.size();
                for (int i = 0; i < rowSize; i++)
                {
                    rows.get(i).setIndex(i);
                }
                setRow(null);
                setTree(null);
                m_targetColumn = null;
            }
        }

        /// <summary>
        /// 移除节点
        /// </summary>
        /// <param name="node">节点</param>
        public virtual void removeNode(FCTreeNode node)
        {
            node.onRemovingNode();
            m_nodes.remove(node);
        }

        /// <summary>
        /// 设置属性
        /// </summary>
        /// <param name="name">属性名</param>
        /// <param name="value">属性值</param>
        public override void setAttribute(String name, String value)
        {
            switch (name)
            {
                case "allowdragin":
                    setAllowDragIn(FCTran.strToBool(value));
                    break;
                case "allowdragout":
                    setAllowDragOut(FCTran.strToBool(value));
                    break;
                case "checked":
                    setChecked(FCTran.strToBool(value));
                    break;
                case "expended":
                    setExpended(FCTran.strToBool(value));
                    break;
                case "value":
                    setValue(value);
                    break;
                default:
                    base.setAttribute(name, value);
                    break;
            }
        }

        /// <summary>
        /// 设置字符型数值
        /// </summary>
        /// <param name="value">数值</param>
        public override void setString(String value)
        {
            m_text = value;
        }
    }
}
